#ifndef __MFSMACHINE_HPP__
#define __MFSMACHINE_HPP__

#include <time.h>
#include "BaseState.hpp"

class MMessage;

template <class entityType, class stateType>
class MFSMachine
{
public:
	MFSMachine(entityType* pOwner)
	{
		m_pMachineOwner = pOwner;
		m_pPreviousState = NULL;
		m_pCurrentState  = NULL;
		m_pListenerState = NULL;
	}

	~MFSMachine()
	{
		if(m_pCurrentState)
		{
			delete m_pCurrentState;
			m_pCurrentState = NULL;
		}

		if(m_pPreviousState)
		{
			delete m_pPreviousState;
			m_pPreviousState = NULL;
		}
	}

	const BaseState<entityType, stateType>* getPreviousState() const
	{
		return m_pPreviousState;
	}

	const BaseState<entityType, stateType>* getCurrentState() const
	{
		return m_pCurrentState;
	}

	void  setCurrentState(BaseState<entityType, stateType>* pState)
	{
		m_pCurrentState = pState;
		pState->beginState(m_pMachineOwner);
	}

	void setListenerState(BaseState<entityType, stateType>* pState)
	{
		m_pListenerState = pState;
		pState->beginState(m_pMachineOwner);
	}
	
	bool  changeState(BaseState<entityType, stateType>* pState)
	{
		//TODO: make protection for valid state change

		bool success = true;
		BaseState<entityType, stateType>* pTempState;

		delete m_pPreviousState;
		m_pPreviousState = m_pCurrentState;

		pTempState = m_pCurrentState;
		m_pCurrentState = pState;

		pTempState->endState(m_pMachineOwner);
		m_pCurrentState->beginState(m_pMachineOwner);

		return success;
	}

	bool  revertToPrevState()
	{
		//TODO: reconsider if this approach is good one

		BaseState<entityType, stateType>* pTempState;

		pTempState = m_pPreviousState;
		m_pPreviousState = m_pCurrentState;
		m_pCurrentState = pTempState;

		m_pCurrentState->resetState();
	}

	void  updateMFSM(clock_t tick)
	{
		if(m_pListenerState)
			m_pListenerState->updateState(m_pMachineOwner, tick);

		if(m_pCurrentState)
			m_pCurrentState->updateState(m_pMachineOwner, tick);
	}

	void handleMessage(MMessage* pMsg)
	{
		m_pListenerState->handleMessage(m_pMachineOwner, pMsg);
	}

private:
	BaseState<entityType, stateType>*   m_pPreviousState;
	BaseState<entityType, stateType>*   m_pCurrentState;
	BaseState<entityType, stateType>*   m_pListenerState;
	entityType*  m_pMachineOwner;
};

#endif //__MFSMACHINE_HPP__

//EOF
